1   /*
2    * Copyright (C) 2008 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.primitives;
18  
19  import static com.google.common.base.Preconditions.checkArgument;
20  import static com.google.common.base.Preconditions.checkElementIndex;
21  import static com.google.common.base.Preconditions.checkNotNull;
22  import static com.google.common.base.Preconditions.checkPositionIndexes;
23  import static java.lang.Double.NEGATIVE_INFINITY;
24  import static java.lang.Double.POSITIVE_INFINITY;
25  
26  import com.google.common.annotations.Beta;
27  import com.google.common.annotations.GwtCompatible;
28  import com.google.common.base.Converter;
29  
30  import java.io.Serializable;
31  import java.util.AbstractList;
32  import java.util.Collection;
33  import java.util.Collections;
34  import java.util.Comparator;
35  import java.util.List;
36  import java.util.RandomAccess;
37  
38  /**
39   * Static utility methods pertaining to {@code double} primitives, that are not
40   * already found in either {@link Double} or {@link Arrays}.
41   *
42   * <p>See the Guava User Guide article on <a href=
43   * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained">
44   * primitive utilities</a>.
45   *
46   * @author Kevin Bourrillion
47   * @since 1.0
48   */
49  @GwtCompatible(emulated = true)
50  public final class Doubles {
51    private Doubles() {}
52  
53    /**
54     * The number of bytes required to represent a primitive {@code double}
55     * value.
56     *
57     * @since 10.0
58     */
59    public static final int BYTES = Double.SIZE / Byte.SIZE;
60  
61    /**
62     * Returns a hash code for {@code value}; equal to the result of invoking
63     * {@code ((Double) value).hashCode()}.
64     *
65     * @param value a primitive {@code double} value
66     * @return a hash code for the value
67     */
68    public static int hashCode(double value) {
69      return ((Double) value).hashCode();
70      // TODO(kevinb): do it this way when we can (GWT problem):
71      // long bits = Double.doubleToLongBits(value);
72      // return (int) (bits ^ (bits >>> 32));
73    }
74  
75    /**
76     * Compares the two specified {@code double} values. The sign of the value
77     * returned is the same as that of <code>((Double) a).{@linkplain
78     * Double#compareTo compareTo}(b)</code>. As with that method, {@code NaN} is
79     * treated as greater than all other values, and {@code 0.0 > -0.0}.
80     *
81     * <p><b>Note:</b> this method simply delegates to the JDK method {@link
82     * Double#compare}. It is provided for consistency with the other primitive
83     * types, whose compare methods were not added to the JDK until JDK 7.
84     *
85     * @param a the first {@code double} to compare
86     * @param b the second {@code double} to compare
87     * @return a negative value if {@code a} is less than {@code b}; a positive
88     *     value if {@code a} is greater than {@code b}; or zero if they are equal
89     */
90    public static int compare(double a, double b) {
91      return Double.compare(a, b);
92    }
93  
94    /**
95     * Returns {@code true} if {@code value} represents a real number. This is
96     * equivalent to, but not necessarily implemented as,
97     * {@code !(Double.isInfinite(value) || Double.isNaN(value))}.
98     *
99     * @since 10.0
100    */
101   public static boolean isFinite(double value) {
102     return NEGATIVE_INFINITY < value & value < POSITIVE_INFINITY;
103   }
104 
105   /**
106    * Returns {@code true} if {@code target} is present as an element anywhere in
107    * {@code array}. Note that this always returns {@code false} when {@code
108    * target} is {@code NaN}.
109    *
110    * @param array an array of {@code double} values, possibly empty
111    * @param target a primitive {@code double} value
112    * @return {@code true} if {@code array[i] == target} for some value of {@code
113    *     i}
114    */
115   public static boolean contains(double[] array, double target) {
116     for (double value : array) {
117       if (value == target) {
118         return true;
119       }
120     }
121     return false;
122   }
123 
124   /**
125    * Returns the index of the first appearance of the value {@code target} in
126    * {@code array}. Note that this always returns {@code -1} when {@code target}
127    * is {@code NaN}.
128    *
129    * @param array an array of {@code double} values, possibly empty
130    * @param target a primitive {@code double} value
131    * @return the least index {@code i} for which {@code array[i] == target}, or
132    *     {@code -1} if no such index exists.
133    */
134   public static int indexOf(double[] array, double target) {
135     return indexOf(array, target, 0, array.length);
136   }
137 
138   // TODO(kevinb): consider making this public
139   private static int indexOf(
140       double[] array, double target, int start, int end) {
141     for (int i = start; i < end; i++) {
142       if (array[i] == target) {
143         return i;
144       }
145     }
146     return -1;
147   }
148 
149   /**
150    * Returns the start position of the first occurrence of the specified {@code
151    * target} within {@code array}, or {@code -1} if there is no such occurrence.
152    *
153    * <p>More formally, returns the lowest index {@code i} such that {@code
154    * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly
155    * the same elements as {@code target}.
156    *
157    * <p>Note that this always returns {@code -1} when {@code target} contains
158    * {@code NaN}.
159    *
160    * @param array the array to search for the sequence {@code target}
161    * @param target the array to search for as a sub-sequence of {@code array}
162    */
163   public static int indexOf(double[] array, double[] target) {
164     checkNotNull(array, "array");
165     checkNotNull(target, "target");
166     if (target.length == 0) {
167       return 0;
168     }
169 
170     outer:
171     for (int i = 0; i < array.length - target.length + 1; i++) {
172       for (int j = 0; j < target.length; j++) {
173         if (array[i + j] != target[j]) {
174           continue outer;
175         }
176       }
177       return i;
178     }
179     return -1;
180   }
181 
182   /**
183    * Returns the index of the last appearance of the value {@code target} in
184    * {@code array}. Note that this always returns {@code -1} when {@code target}
185    * is {@code NaN}.
186    *
187    * @param array an array of {@code double} values, possibly empty
188    * @param target a primitive {@code double} value
189    * @return the greatest index {@code i} for which {@code array[i] == target},
190    *     or {@code -1} if no such index exists.
191    */
192   public static int lastIndexOf(double[] array, double target) {
193     return lastIndexOf(array, target, 0, array.length);
194   }
195 
196   // TODO(kevinb): consider making this public
197   private static int lastIndexOf(
198       double[] array, double target, int start, int end) {
199     for (int i = end - 1; i >= start; i--) {
200       if (array[i] == target) {
201         return i;
202       }
203     }
204     return -1;
205   }
206 
207   /**
208    * Returns the least value present in {@code array}, using the same rules of
209    * comparison as {@link Math#min(double, double)}.
210    *
211    * @param array a <i>nonempty</i> array of {@code double} values
212    * @return the value present in {@code array} that is less than or equal to
213    *     every other value in the array
214    * @throws IllegalArgumentException if {@code array} is empty
215    */
216   public static double min(double... array) {
217     checkArgument(array.length > 0);
218     double min = array[0];
219     for (int i = 1; i < array.length; i++) {
220       min = Math.min(min, array[i]);
221     }
222     return min;
223   }
224 
225   /**
226    * Returns the greatest value present in {@code array}, using the same rules
227    * of comparison as {@link Math#max(double, double)}.
228    *
229    * @param array a <i>nonempty</i> array of {@code double} values
230    * @return the value present in {@code array} that is greater than or equal to
231    *     every other value in the array
232    * @throws IllegalArgumentException if {@code array} is empty
233    */
234   public static double max(double... array) {
235     checkArgument(array.length > 0);
236     double max = array[0];
237     for (int i = 1; i < array.length; i++) {
238       max = Math.max(max, array[i]);
239     }
240     return max;
241   }
242 
243   /**
244    * Returns the values from each provided array combined into a single array.
245    * For example, {@code concat(new double[] {a, b}, new double[] {}, new
246    * double[] {c}} returns the array {@code {a, b, c}}.
247    *
248    * @param arrays zero or more {@code double} arrays
249    * @return a single array containing all the values from the source arrays, in
250    *     order
251    */
252   public static double[] concat(double[]... arrays) {
253     int length = 0;
254     for (double[] array : arrays) {
255       length += array.length;
256     }
257     double[] result = new double[length];
258     int pos = 0;
259     for (double[] array : arrays) {
260       System.arraycopy(array, 0, result, pos, array.length);
261       pos += array.length;
262     }
263     return result;
264   }
265 
266   private static final class DoubleConverter
267       extends Converter<String, Double> implements Serializable {
268     static final DoubleConverter INSTANCE = new DoubleConverter();
269 
270     @Override
271     protected Double doForward(String value) {
272       return Double.valueOf(value);
273     }
274 
275     @Override
276     protected String doBackward(Double value) {
277       return value.toString();
278     }
279 
280     @Override
281     public String toString() {
282       return "Doubles.stringConverter()";
283     }
284 
285     private Object readResolve() {
286       return INSTANCE;
287     }
288     private static final long serialVersionUID = 1;
289   }
290 
291   /**
292    * Returns a serializable converter object that converts between strings and
293    * doubles using {@link Double#valueOf} and {@link Double#toString()}.
294    *
295    * @since 16.0
296    */
297   @Beta
298   public static Converter<String, Double> stringConverter() {
299     return DoubleConverter.INSTANCE;
300   }
301 
302   /**
303    * Returns an array containing the same values as {@code array}, but
304    * guaranteed to be of a specified minimum length. If {@code array} already
305    * has a length of at least {@code minLength}, it is returned directly.
306    * Otherwise, a new array of size {@code minLength + padding} is returned,
307    * containing the values of {@code array}, and zeroes in the remaining places.
308    *
309    * @param array the source array
310    * @param minLength the minimum length the returned array must guarantee
311    * @param padding an extra amount to "grow" the array by if growth is
312    *     necessary
313    * @throws IllegalArgumentException if {@code minLength} or {@code padding} is
314    *     negative
315    * @return an array containing the values of {@code array}, with guaranteed
316    *     minimum length {@code minLength}
317    */
318   public static double[] ensureCapacity(
319       double[] array, int minLength, int padding) {
320     checkArgument(minLength >= 0, "Invalid minLength: %s", minLength);
321     checkArgument(padding >= 0, "Invalid padding: %s", padding);
322     return (array.length < minLength)
323         ? copyOf(array, minLength + padding)
324         : array;
325   }
326 
327   // Arrays.copyOf() requires Java 6
328   private static double[] copyOf(double[] original, int length) {
329     double[] copy = new double[length];
330     System.arraycopy(original, 0, copy, 0, Math.min(original.length, length));
331     return copy;
332   }
333 
334   /**
335    * Returns a string containing the supplied {@code double} values, converted
336    * to strings as specified by {@link Double#toString(double)}, and separated
337    * by {@code separator}. For example, {@code join("-", 1.0, 2.0, 3.0)} returns
338    * the string {@code "1.0-2.0-3.0"}.
339    *
340    * <p>Note that {@link Double#toString(double)} formats {@code double}
341    * differently in GWT sometimes.  In the previous example, it returns the
342    * string {@code "1-2-3"}.
343    *
344    * @param separator the text that should appear between consecutive values in
345    *     the resulting string (but not at the start or end)
346    * @param array an array of {@code double} values, possibly empty
347    */
348   public static String join(String separator, double... array) {
349     checkNotNull(separator);
350     if (array.length == 0) {
351       return "";
352     }
353 
354     // For pre-sizing a builder, just get the right order of magnitude
355     StringBuilder builder = new StringBuilder(array.length * 12);
356     builder.append(array[0]);
357     for (int i = 1; i < array.length; i++) {
358       builder.append(separator).append(array[i]);
359     }
360     return builder.toString();
361   }
362 
363   /**
364    * Returns a comparator that compares two {@code double} arrays
365    * lexicographically. That is, it compares, using {@link
366    * #compare(double, double)}), the first pair of values that follow any
367    * common prefix, or when one array is a prefix of the other, treats the
368    * shorter array as the lesser. For example,
369    * {@code [] < [1.0] < [1.0, 2.0] < [2.0]}.
370    *
371    * <p>The returned comparator is inconsistent with {@link
372    * Object#equals(Object)} (since arrays support only identity equality), but
373    * it is consistent with {@link Arrays#equals(double[], double[])}.
374    *
375    * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order">
376    *     Lexicographical order article at Wikipedia</a>
377    * @since 2.0
378    */
379   public static Comparator<double[]> lexicographicalComparator() {
380     return LexicographicalComparator.INSTANCE;
381   }
382 
383   private enum LexicographicalComparator implements Comparator<double[]> {
384     INSTANCE;
385 
386     @Override
387     public int compare(double[] left, double[] right) {
388       int minLength = Math.min(left.length, right.length);
389       for (int i = 0; i < minLength; i++) {
390         int result = Double.compare(left[i], right[i]);
391         if (result != 0) {
392           return result;
393         }
394       }
395       return left.length - right.length;
396     }
397   }
398 
399   /**
400    * Returns an array containing each value of {@code collection}, converted to
401    * a {@code double} value in the manner of {@link Number#doubleValue}.
402    *
403    * <p>Elements are copied from the argument collection as if by {@code
404    * collection.toArray()}.  Calling this method is as thread-safe as calling
405    * that method.
406    *
407    * @param collection a collection of {@code Number} instances
408    * @return an array containing the same values as {@code collection}, in the
409    *     same order, converted to primitives
410    * @throws NullPointerException if {@code collection} or any of its elements
411    *     is null
412    * @since 1.0 (parameter was {@code Collection<Double>} before 12.0)
413    */
414   public static double[] toArray(Collection<? extends Number> collection) {
415     if (collection instanceof DoubleArrayAsList) {
416       return ((DoubleArrayAsList) collection).toDoubleArray();
417     }
418 
419     Object[] boxedArray = collection.toArray();
420     int len = boxedArray.length;
421     double[] array = new double[len];
422     for (int i = 0; i < len; i++) {
423       // checkNotNull for GWT (do not optimize)
424       array[i] = ((Number) checkNotNull(boxedArray[i])).doubleValue();
425     }
426     return array;
427   }
428 
429   /**
430    * Returns a fixed-size list backed by the specified array, similar to {@link
431    * Arrays#asList(Object[])}. The list supports {@link List#set(int, Object)},
432    * but any attempt to set a value to {@code null} will result in a {@link
433    * NullPointerException}.
434    *
435    * <p>The returned list maintains the values, but not the identities, of
436    * {@code Double} objects written to or read from it.  For example, whether
437    * {@code list.get(0) == list.get(0)} is true for the returned list is
438    * unspecified.
439    *
440    * <p>The returned list may have unexpected behavior if it contains {@code
441    * NaN}, or if {@code NaN} is used as a parameter to any of its methods.
442    *
443    * @param backingArray the array to back the list
444    * @return a list view of the array
445    */
446   public static List<Double> asList(double... backingArray) {
447     if (backingArray.length == 0) {
448       return Collections.emptyList();
449     }
450     return new DoubleArrayAsList(backingArray);
451   }
452 
453   @GwtCompatible
454   private static class DoubleArrayAsList extends AbstractList<Double>
455       implements RandomAccess, Serializable {
456     final double[] array;
457     final int start;
458     final int end;
459 
460     DoubleArrayAsList(double[] array) {
461       this(array, 0, array.length);
462     }
463 
464     DoubleArrayAsList(double[] array, int start, int end) {
465       this.array = array;
466       this.start = start;
467       this.end = end;
468     }
469 
470     @Override public int size() {
471       return end - start;
472     }
473 
474     @Override public boolean isEmpty() {
475       return false;
476     }
477 
478     @Override public Double get(int index) {
479       checkElementIndex(index, size());
480       return array[start + index];
481     }
482 
483     @Override public boolean contains(Object target) {
484       // Overridden to prevent a ton of boxing
485       return (target instanceof Double)
486           && Doubles.indexOf(array, (Double) target, start, end) != -1;
487     }
488 
489     @Override public int indexOf(Object target) {
490       // Overridden to prevent a ton of boxing
491       if (target instanceof Double) {
492         int i = Doubles.indexOf(array, (Double) target, start, end);
493         if (i >= 0) {
494           return i - start;
495         }
496       }
497       return -1;
498     }
499 
500     @Override public int lastIndexOf(Object target) {
501       // Overridden to prevent a ton of boxing
502       if (target instanceof Double) {
503         int i = Doubles.lastIndexOf(array, (Double) target, start, end);
504         if (i >= 0) {
505           return i - start;
506         }
507       }
508       return -1;
509     }
510 
511     @Override public Double set(int index, Double element) {
512       checkElementIndex(index, size());
513       double oldValue = array[start + index];
514       // checkNotNull for GWT (do not optimize)
515       array[start + index] = checkNotNull(element);
516       return oldValue;
517     }
518 
519     @Override public List<Double> subList(int fromIndex, int toIndex) {
520       int size = size();
521       checkPositionIndexes(fromIndex, toIndex, size);
522       if (fromIndex == toIndex) {
523         return Collections.emptyList();
524       }
525       return new DoubleArrayAsList(array, start + fromIndex, start + toIndex);
526     }
527 
528     @Override public boolean equals(Object object) {
529       if (object == this) {
530         return true;
531       }
532       if (object instanceof DoubleArrayAsList) {
533         DoubleArrayAsList that = (DoubleArrayAsList) object;
534         int size = size();
535         if (that.size() != size) {
536           return false;
537         }
538         for (int i = 0; i < size; i++) {
539           if (array[start + i] != that.array[that.start + i]) {
540             return false;
541           }
542         }
543         return true;
544       }
545       return super.equals(object);
546     }
547 
548     @Override public int hashCode() {
549       int result = 1;
550       for (int i = start; i < end; i++) {
551         result = 31 * result + Doubles.hashCode(array[i]);
552       }
553       return result;
554     }
555 
556     @Override public String toString() {
557       StringBuilder builder = new StringBuilder(size() * 12);
558       builder.append('[').append(array[start]);
559       for (int i = start + 1; i < end; i++) {
560         builder.append(", ").append(array[i]);
561       }
562       return builder.append(']').toString();
563     }
564 
565     double[] toDoubleArray() {
566       // Arrays.copyOfRange() is not available under GWT
567       int size = size();
568       double[] result = new double[size];
569       System.arraycopy(array, start, result, 0, size);
570       return result;
571     }
572 
573     private static final long serialVersionUID = 0;
574   }
575 }